/*
 * Created on Jan 1, 2005
 *
 */
package com.aicode.core.tools.core.model.db.table.model;



import com.aicode.core.tools.core.ListHashtable;
import com.aicode.core.tools.core.StringHelper;
import com.aicode.core.tools.core.model.db.table.TableFactory;

import java.util.List;

/**
 * @author chris
 */
public class ForeignKey implements java.io.Serializable {


    protected String relationShip = null;
    protected String firstRelation = null;
    protected String secondRelation = null;
    protected Table parentTable;
    protected String tableName;
    protected ListHashtable columns;
    protected ListHashtable parentColumns;

    public ForeignKey(Table aTable, String tblName) {
        super();
        parentTable = aTable;
        tableName = tblName;
        columns = new ListHashtable();
        parentColumns = new ListHashtable();
    }

    /**
     * @return Returns the tableName.
     */
    public String getTableName() {
        return tableName;
    }

    public String getParentTableName() {
        return parentTable.getSqlName();
    }

    /**
     * @param col
     * @param seq
     */
    public void addColumn(String col, String parentCol, Integer seq) {
        columns.put(seq, col);
        parentColumns.put(seq, parentCol);
    }

    public String getColumn(String parentCol) {
        // return the associated column given the parent column
        Object key = parentColumns.getKeyForValue(parentCol);
        String col = (String) columns.get(key);
        //System.out.println("get Column for" +parentCol);
        //System.out.println("key = "+key);
        //System.out.println("col="+col);
        //System.out.println("ParentColumns = "+parentColumns.toString());
        return col;
    }

    public ListHashtable getColumns() {
        return columns;
    }

    /**
     *
     */
    private void initRelationship() {
        firstRelation = "";
        secondRelation = "";
        Table foreignTable = null;
        try {
            foreignTable = (Table) TableFactory.getInstance().getTable(tableName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List parentPrimaryKeys = parentTable.getPrimaryKeyColumns();
        List foreignPrimaryKeys = foreignTable.getPrimaryKeyColumns();

        if (hasAllPrimaryKeys(parentPrimaryKeys, parentColumns)) {
            firstRelation = "one";
        } else {
            firstRelation = "many";
        }

        if (hasAllPrimaryKeys(foreignPrimaryKeys, columns)) {
            secondRelation = "one";
        } else {
            secondRelation = "many";
        }

        relationShip = firstRelation + "-to-" + secondRelation;

    }

    private boolean hasAllPrimaryKeys(List pkeys, ListHashtable cols) {
        boolean hasAll = true;
        // if size is not equal then false
        int numKeys = pkeys.size();
        if (numKeys != cols.size()) {
            return false;
        }

        for (int i = 0; i < numKeys; i++) {
            Column col = (Column) pkeys.get(i);
            String colname = col.getColumnName();
            if (!cols.contains(colname)) {
                return false;
            }
        }

        return hasAll;
    }

    public boolean isParentColumnsFromPrimaryKey() {
        boolean isFrom = true;
        List keys = parentTable.getPrimaryKeyColumns();
        int numKeys = getParentColumns().size();
        for (int i = 0; i < numKeys; i++) {
            String pcol = (String) getParentColumns().getOrderedValue(i);
            if (!primaryKeyHasColumn(pcol)) {
                isFrom = false;
                break;
            }
        }
        return isFrom;
    }

    private boolean primaryKeyHasColumn(String aColumn) {
        boolean isFound = false;
        int numKeys = parentTable.getPrimaryKeyColumns().size();
        for (int i = 0; i < numKeys; i++) {
            Column sqlCol = (Column) parentTable.getPrimaryKeyColumns().get(i);
            String colname = sqlCol.getColumnName();
            if (colname.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return isFound;
    }

    public boolean getHasImportedKeyColumn(String aColumn) {
        boolean isFound = false;
        List cols = getColumns().getOrderedValues();
        int numCols = cols.size();
        for (int i = 0; i < numCols; i++) {
            String col = (String) cols.get(i);
            if (col.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return isFound;
    }

    /**
     * @return Returns the firstRelation.
     */
    public String getFirstRelation() {
        if (firstRelation == null) {
            initRelationship();
        }
        return firstRelation;
    }

    public Table getSqlTable() {
        Table table = null;
        try {
            table = (Table) TableFactory.getInstance().getTable(tableName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }

    /**
     * @return Returns the parentTable.
     */
    public Table getParentTable() {
        return parentTable;
    }

    /**
     * @return Returns the relationShip.
     */
    public String getRelationShip() {
        if (relationShip == null) {
            initRelationship();
        }
        return relationShip;
    }

    /**
     * @return Returns the secondRelation.
     */
    public String getSecondRelation() {
        if (secondRelation == null) {
            initRelationship();
        }
        return secondRelation;
    }

    /**
     * @return Returns the parentColumns.
     */
    public ListHashtable getParentColumns() {
        return parentColumns;
    }

    public boolean getHasImportedKeyParentColumn(String aColumn) {

        boolean isFound = false;
        List cols = getParentColumns().getOrderedValues();
        int numCols = cols.size();
        for (int i = 0; i < numCols; i++) {
            String col = (String) cols.get(i);
            if (col.equals(aColumn)) {
                isFound = true;
                break;
            }
        }
        return isFound;
    }

    /**
     * 外键引用使用的值对象
     *
     * @author Lixin
     */
    public static class ReferenceKey implements java.io.Serializable {
        public String schemaName;
        public String tableName;
        public String columnSqlName;

        public ReferenceKey(String schemaName, String tableName, String columnSqlName) {
            this.schemaName = StringHelper.defaultIfEmpty(schemaName, null);
            this.tableName = tableName;
            this.columnSqlName = columnSqlName;
        }

        @Override
        public String toString() {
            if (StringHelper.isBlank(schemaName)) {
                return tableName + "(" + columnSqlName + ")";
            } else {
                return schemaName + "." + tableName + "(" + columnSqlName + ")";
            }
        }

        public static String toString(ReferenceKey k) {
            if (k == null) {
                return null;
            }
            return k.toString();
        }

        /**
         * 解析foreignKey字符串,格式: fk_table_name(fk_column) 或者 schema_name.fk_table_name(fk_column)
         *
         * @param foreignKey
         * @return
         */
        public static ReferenceKey fromString(String foreignKey) {
            if (StringHelper.isBlank(foreignKey)) {
                return null;
            }
            if (!foreignKey.trim().matches(".*\\w+\\(.*\\)")) {
                throw new IllegalArgumentException("Illegal foreignKey:[" + foreignKey + "] ,example value: fk_table_name(fk_column) ");
            }
            String schemaName = foreignKey.substring(0, Math.max(foreignKey.lastIndexOf("."), 0));
            String tableSqlName = foreignKey.substring(Math.max(foreignKey.lastIndexOf(".") + 1, 0), foreignKey.indexOf("("));
            String columnSqlName = foreignKey.substring(foreignKey.indexOf("(") + 1, foreignKey.indexOf(")"));
            return new ReferenceKey(schemaName, tableSqlName, columnSqlName);
        }
    }
}
